<?php

/**
 * Contains a class to define a Map object to describe a map view.
 *
 * PHP Version 5
 *
 * @category BuyLocal
 * @package  BuyLocal
 * @author   Kevin Fodness <kevin.fodness@gmail.com>
 * @author   Mike Pennisi <mpennisi@andrew.cmu.edu>
 * @author   Aaron Ryden <aryden@gmail.com>
 * @author   Spencer Hakim <hakims@rpi.edu>
 * @license  http://opensource.org/licenses/gpl-license.php GNU Public License
 * @link     http://code.google.com/p/buylocalopensourcerensselaer/
 */

/** @uses encode For safe display of content. */
require_once 'function_encode.php';
 
/**
 * A class to define a Map object to describe a map view.
 *
 * @category BuyLocal
 * @package  BuyLocal
 * @author   Kevin Fodness <kevin.fodness@gmail.com>
 * @author   Mike Pennisi <mpennisi@andrew.cmu.edu>
 * @author   Aaron Ryden <aryden@gmail.com>
 * @author   Spencer Hakim <hakims@rpi.edu>
 * @license  http://opensource.org/licenses/gpl-license.php GNU Public License
 * @link     http://code.google.com/p/buylocalopensourcerensselaer/
 */ 
class Map
{
    /**
     * Variable to contain the stores/events being displayed on the map.
     *
     * @access public
     * @var array     An array of Store/Event objects.
     */
    public $stores;
    
    /**
     * Constructor function.  Populates variables based on parameters.
     *
     * @param mixed $stores A single Store/Event or an array of Stores/Events.
     *
     * @access public
     * @return null
     */
    public function __construct($stores)
    {
        if (!is_array($stores)) {
            $stores = array($stores);
        }
        $this->stores = $stores;
    }
    
    /**
     * Function to print the map.
     *
     * @access public
     * @return null
     */
    public function display()
    {
        /** If there are no stores/events to display, quits the function. */
        if (count($this->stores) == 0) {
            return null;
        }
        
        /** Establishes initial values for the bounding box and the map center. */
        $centerStore = reset($this->stores);
        $lowerLat    = $centerStore->latitude;
        $lowerLng    = $centerStore->longitude;
        $upperLat    = $centerStore->latitude;
        $upperLng    = $centerStore->longitude;
        
        /** Includes the JavaScript libraries necessary to display the map. */
        echo ' <script type="text/javascript" src="', RELATIVE_PATH,
            'scripts/map.js"></script>', "\n",
            ' <script type="text/javascript" src="', GM_URL, '"></script>',
            "\n";

        /** Prints the map and the stores/events. */
        echo ' <div id="map_canvas"></div>', "\n",
            ' <script type="text/javascript">', "\n",
            '  <!--', "\n",
            '   initialize(\'', RELATIVE_PATH, '\');', "\n",
            '   centerMap(', $centerStore->latitude, ',', 
            $centerStore->longitude, ');', "\n";
        foreach ($this->stores as $store) {
            /** Adjusts the bounding box coordinates if necessary. */
            if ($store->latitude < $lowerLat) {
                $lowerLat = $store->latitude;
            }
            if ($store->longitude < $lowerLng) {
                $lowerLng = $store->longitude;
            }
            if ($store->latitude > $upperLat) {
                $upperLat = $store->latitude;
            }
            if ($store->longitude > $upperLng) {
                $upperLng = $store->longitude;
            }

            /** Ugly hack for ZIP inconsistency */
            if (is_object($store->zip)) {
                $store->zip = $store->zip->zip;
            }
            
            /** Builds the infoWindow for the store/event. */
            if (get_class($store) == 'Event') {
                $infoWindow = '<img align="right" src="' . $store->imagePath
                    . '"/><a href="' . RELATIVE_PATH . 'event.php?eventid='
                    . $store->id . '">' . encode($store->name) . '</a>'
                    . '<address>' . encode($store->address) . '<br/>'
                    . encode($store->city) . ', ' . encode($store->state) . ' '
                    . encode($store->zip) . '<br/>' . encode($store->country)
                    . '</address>';
            } else {
                $infoWindow = '<img align="right" src="' . $store->imagePath
                    . '"/><a href="' . RELATIVE_PATH . 'stores.php?storeid='
                    . $store->id . '">' . encode($store->name) . '</a>'
                    . '<address>' . encode($store->address) . '<br/>'
                    . encode($store->city) . ', ' . encode($store->state) . ' '
                    . encode($store->zip) . '<br/>' . encode($store->country)
                    . '</address>';
            }
            $infoWindow = addslashes($infoWindow);
                
            /** Adds the store/event to the map. */
            echo '   addStore(', $store->latitude, ',',
                $store->longitude, ', \'', addslashes(encode($store->name)),
                '\', \'', $infoWindow, '\');', "\n";
        }
        
        /**
         * Pads the bounding box coordinates by 10% based on distance from the
         * center with a constant value added to acommodate close-range maps.
         */
        $lowerLat -= ($centerStore->latitude - $lowerLat) * 0.1 + 0.01;
        $lowerLng -= ($centerStore->longitude - $lowerLng) * 0.1 + 0.02;
        $upperLat += ($upperLat - $centerStore->latitude) * 0.1 + 0.01;
        $upperLng += ($upperLng - $centerStore->longitude) * 0.1 + 0.02;
        
        /** Zooms the map based on the bounding box and closes the script tag. */
        echo '   zoomMap(', $lowerLat, ', ', $lowerLng, ', ',
            $upperLat, ', ', $upperLng, ');', "\n",
            '  //-->', "\n",
            ' </script>', "\n";
    }
}

?>